import { Component, ComponentType } from "./Component";
import { any } from "../core/logic";
import { ids } from "../core/ids";
import { Register } from "../register/Register";
import { Engine } from "../Engine";
class Board extends Component {
    constructor(opts = {}) {
        opts.type = any(opts.type, ComponentType.Board);
        opts.id = ids.generate();//生成颜色id
        super(opts);
        this.side=any(opts.side,"front");//可以是前面绘制"front"，背面绘制:"back"，双面绘制:"none"。
        this._gamma=any(opts.gamma,0.1);
        //布局参数
        this.pixelUnit=any(opts.pixelUnit,true);
        this.offset=any(opts.offset,[0,0]);
        this.border=any(opts.border,[2,2]);
        this.depthBias=any(opts.depthBias,-50);
        this.depthBiasSlopeScale=any(opts.depthBias,1);
        this.depthBiasClamp=any(opts.depthBiasClamp,0);
        //背景参数
        this._background = any(opts.background, true);
        this._backgroundColor = any(opts.backgroundColor, "#ffffff");
        this._backgroundImage = opts.backgroundImage;
        this._blending=any(opts.blending,"NormalBlending")
        //文字参数
        this.fontUrl=opts.fontUrl;
        this.fontSize = any(opts.fontSize, 16);
        this.width = any(opts.width, 160);
        // this.textWidth = any(opts.textWidth, 160);
        this._fontColor = any(opts.fontColor, "#000000");
        this.labelField = any(opts.labelField, "name");
        this.fontMaterial=any(opts.fontMaterial,new w.material.BasicMaterial({
            color: this.fontColor,
            side:this.side,
            map: this.fontUrl+"atlas.png", sdf: true,
            alphaCutoff: 0.0,
            transparent:true,
            blending: "NormalBlending",
            opacity: 1.0,
            mipMap:true,
            depthBias:this.depthBias,
            depthBiasSlopeScale:this.depthBiasSlopeScale,
            depthBiasClamp:this.depthBiasClamp,
            sdfFrom: 0.75,
            defuseLight: true,
            sdfTo: this.gamma
        }));
        this.backMaterial = new w.material.BasicMaterial({
            color: this.backgroundColor,
            map:this.backgroundImage,
            alphaCutoff: 0.3,
            // transparent:true,
            blending: "NormalBlending",
            // mipMap:true,
            defuseLight: true,
            side:this.side
        });
        this.signs = new Map();
        this.params=opts.params
        this.update();
    }
    get textWidth(){
        return this.width-this.border[0]*2;
    }
    get blending(){
        return this._blending;
    }
    set blending(v){
        this._blending=v;
        this.backMaterial.blending=v;
        return this;
    }
    get params(){
        return this._params;
    }
    set params(v){
        if(this.object3D){
            this.object3D.params=v
        }
        this._params=v
        return this;
    }
    get background(){
        return this._background;
    }
    set background(v){
        if(v!=this.background){
            this._background=v;
            for(let [key,value] of this.signs){
                value.background.visibility=v;
            }
        }
    }
    get gamma(){
        return this._gamma;
    }
    set gamma(v){
        if(v!=this.gamma){
            this._gamma=v;
            this.fontMaterial.sdfTo=v;
        }
    }
    get backgroundColor(){
        return this._backgroundColor;
    }
    set backgroundColor(v){
        this._backgroundColor=v;
        this.backMaterial.color=v;
        return this;
    }
    get backgroundImage(){
        return this._backgroundImage;
    }
    set backgroundImage(v){
        this._backgroundImage=v;
        this.backMaterial.map=v;
        return this;
    }
    get fontColor(){
        return this._fontColor;
    }
    set fontColor(v){
        this.fontMaterial.color=v;
        this._fontColor=v;
        return this;
    }

    getTrans() {
        if (!this.eids) {
            return null;
        }
        let eid = [...this.eids][0];
        if (!eid) {
            return null;
        }
        const entity = Register.instance.entityManager.get(eid);
        if (!entity) {
            return null;
        }
        return entity.trans;
    }
    update() {
        const trans = this.getTrans();
        if (!trans) {
            return;
        }
        if (trans.hash == "trans") {
            this.updateBoard(trans);
        } else {
            for (let i = 0; i < trans._transArr.length; i++) {
                this.updateBoard(trans._transArr[i]);
            }
        }
    }
    updateBoard(trans) {
        if (!trans) {
            return;
        }
        if(!trans.parameter){
            return;
        }
        let text=trans.parameter[this.labelField];
        if(!text||text==""){
            return;
        }
        let id = trans.id;
        if (this.signs.has(id)) {
            //更新现有的
            let board = this.signs.get(id);
            board.text.update(trans,true);
            board.background.update(trans,true);
        } else {
            //创建新的
            let board = {};
            board.text = new Text(this,trans);
            board.background = new Background(this,trans);
            this.signs.set(id, board);
        }
    }
    removeAll(){
       for(let [key,value] of this.signs){
            value.text.destroy();
            value.text=null;
            value.background.destroy();
            value.background=null;
       }
       this.signs.clear();
    }
    destroy(){
        this.removeAll();
        this.fontMaterial.destroy();
        this.fontMaterial=null;
        this.backMaterial.destroy();
        this.backMaterial=null;
    }
    get visibility(){
        return this._visibility;
    }
    set visibility(flag){
        if(flag!=this.visibility){
            for(let [key,value] of this.signs){
                value.text.visibility=flag;
                value.background.visibility=flag;
           } 
           this._visibility=flag;
        }
        
    }
}
class Background {//背景
    constructor(context,trans) {
        this.context=context;
        this.trans=trans;
        const label=trans.parameter[this.context.labelField]?trans.parameter[this.context.labelField]:"";
        let l = this.getBytes(label);
        let bw = this.context.width;
        let hs = Math.ceil(l *this.context.fontSize / 2 / this.context.textWidth);
        this.geometry = new w.geometry.PointGeometry({
            position: new Float32Array([0, 0, 0]),
            size: [bw, (this.context.fontSize) * hs+this.context.border[1]*2],
            verticalLocation:'bottom',
            relativeShift:this.context.offset,
            horizontalLocation:"center",
            pixelUnit:this.context.pixelUnit,
            shape: 'rect' });

        this.mesh = new w.component.Mesh({ geometry: this.geometry, material: this.context.backMaterial })
        this.object3D = new w.Object3D({ position: trans.position.toArray()});
        if(context.params){
            this.object3D.params=context.params
        }
        this.object3D.addComponent(this.mesh);
        Engine.instance.scene.addEntity(this.object3D);
        this.visibility=this.context.background;
    }
    set visibility(v){
        this._visibility=v;
        this.object3D.visibility=v;
        return this;
    }
    get visibility(){
        return this._visibility;
    }
    getBytes(params) {
        let bytes = params.length;
        for (let i = 0; i < bytes; i++) if (params.charCodeAt(i) > 255) bytes++;
        return bytes;
    }
    update(trans) {
        this.object3D.trans.position=trans.position.toArray();
    }
    destroy(){
        this.object3D.destroy();
    }
}
class Text {//文字
    constructor(context,trans) {
        this.context=context;
        this.trans=trans;
        const label=trans.parameter[this.context.labelField]?trans.parameter[this.context.labelField]:"";
        this.geometry = new w.geometry.TextGeometry({
            data: {
                position: [[0, 0, 0]],
                text: [label]
            },
            fontUrl: this.context.fontUrl,//文字字体atlas.json文件所在路径
            width: this.context.textWidth,//文字容器像素宽度
            fontSize: [this.context.fontSize, this.context.fontSize],//文字字体大小
            lineHeight: this.context.fontSize,//文字行高
            space: 0,//文字字符间距
            overflow: 'ellipsis',//文字溢出样式,设置了容器高度为固定值并当文字内容超出容器时生效，ellipsis省略号，hidden隐藏
            textAlign: 'center',//文字在容器内水平居中方式left,center,right
            verticalAlign: 'middle',//文字在容器内垂直居中方式top,middle,bottom
            horizontalLocation: 'center',//文字相对于位置中心的水平位置left,center,right
            verticalLocation: 'bottom',//文字相对于位置中心的垂直位置top,middle,bottom
            pixelUnit:this.context.pixelUnit,
            relativeShift: [this.context.offset[0],this.context.offset[1]+this.context.border[1]],//文字相对于位置中心的偏移
        });
        this.mesh = new w.component.Mesh({ geometry:this.geometry, material:this.context.fontMaterial })
        this.object3D = new w.Object3D({ position: trans.position.toArray() });
        if(context.params){
            this.object3D.params=context.params
        }
        this.object3D.addComponent(this.mesh);
        Engine.instance.scene.addEntity(this.object3D);
        this._visibility=true;
    }
    set visibility(v){
        this._visibility=v;
        this.object3D.visibility=v;
        return this;
    }
    get visibility(){
        return this._visibility;
    }
    update(trans) {
        this.object3D.trans.position=trans.position.toArray();
        const label=trans.parameter[this.context.labelField]?trans.parameter[this.context.labelField]:"";
        this.geometry.fontSize=[this.fontSize,this.fontSize];
        this.geometry.data={
            position: [[0, 0, 0]],
            text: [label]
        }
    }
    destroy(){
        this.object3D.destroy();
    }
}
export { Board }
